#include "commonheader.h"
#include "ListenSocket.h"
#include "HttpTurnnel.h"
#include <iostream>

using namespace std;
CInitSock* CInitSock::mThis = NULL;

static void ReportStatus(DWORD inCurrentState, DWORD inExitCode);
void WINAPI ServiceControl(DWORD);
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);

static SERVICE_STATUS_HANDLE sServiceStatusHandle = 0;
HANDLE gServiceCloseEvent;


void AccpetFunction(SOCKET sClient, SOCKADDR_IN clientAddr)
{
	CHttpTurnnel *turnnel = new CHttpTurnnel(sClient);
	turnnel->InitTurnnel();
}

int main(int argc, char*argv[])
{
	CInitSock::Initial();

	if (argc == 2 && string(argv[1]) == "-d") {
		CListenSocket listen(11111, AccpetFunction);
		listen.Start();
		cout << "Runnint" << endl;
		getchar();
		return 0;
	}

	SERVICE_TABLE_ENTRY dispatchTable[] =
	{
		{ "", ServiceMain },
		{ NULL, NULL }
	};

	BOOL theErr = ::StartServiceCtrlDispatcher(dispatchTable);
	if (!theErr)
	{
		int ret = GetLastError();
		if (ret == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) {
		}
		::exit(-1);
	}

	return 0;
}
void __stdcall ServiceMain(DWORD /*argc*/, LPTSTR *argv)
{
	gServiceCloseEvent = CreateEvent(NULL, TRUE, FALSE, "Start IProxy Services");
	if (!gServiceCloseEvent) {
		::ReportStatus(SERVICE_STOPPED, ERROR_BAD_COMMAND); // I dunno... report some error
		return;
	}

	char* theServerName = argv[0];
	sServiceStatusHandle = ::RegisterServiceCtrlHandler(theServerName, &ServiceControl);
	if (sServiceStatusHandle == 0)
	{
		::ReportStatus(SERVICE_STOPPED, ERROR_BAD_COMMAND); // I dunno... report some error
		return;
	}

	//
	// Report our status
	::ReportStatus(SERVICE_START_PENDING, NO_ERROR);

	//
	// Start & Run the server - no stats update interval for now
	CListenSocket listen(11111, AccpetFunction);
	//listen.Start();
	if (listen.Start())//::StartServer(sXMLParser, &sMessagesSource, sPort, sStatsUpdateInterval, sInitialState, false, 0, kRunServerDebug_Off) != qtssFatalErrorState)
	{
		::ReportStatus(SERVICE_RUNNING, NO_ERROR);
		//::RunServer(); // This function won't return until the server has died

		WaitForSingleObject(gServiceCloseEvent, INFINITE);
		//
		// Ok, server is done...
		::ReportStatus(SERVICE_STOPPED, NO_ERROR);
	}
	else
		::ReportStatus(SERVICE_STOPPED, ERROR_BAD_COMMAND); // I dunno... report some error
}

void WINAPI ServiceControl(DWORD inControlCode)
{
	DWORD theStatusReport = SERVICE_START_PENDING;

	switch (inControlCode)
	{
		// Stop the service.
		//
	case SERVICE_CONTROL_STOP:
	case SERVICE_CONTROL_SHUTDOWN:
	{
		theStatusReport = SERVICE_STOP_PENDING;
		SetEvent(gServiceCloseEvent);
		break;
	}
	case SERVICE_CONTROL_PAUSE:
	{
		theStatusReport = SERVICE_PAUSED;
		break;
	}
	case SERVICE_CONTROL_CONTINUE:
	{
		theStatusReport = SERVICE_RUNNING;
		break;
	}
	case SERVICE_CONTROL_INTERROGATE:
		break; // Just update our status

	default:
		theStatusReport = SERVICE_RUNNING;
		break;
	}

	::ReportStatus(theStatusReport, NO_ERROR);
}

void ReportStatus(DWORD inCurrentState, DWORD inExitCode)
{
	static BOOL sFirstTime = 1;
	static UINT32 sCheckpoint = 0;
	static SERVICE_STATUS sStatus;

	if (sFirstTime)
	{
		sFirstTime = false;

		//
		// Setup the status structure
		sStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
		sStatus.dwCurrentState = SERVICE_START_PENDING;
		//sStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
		sStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
		sStatus.dwWin32ExitCode = 0;
		sStatus.dwServiceSpecificExitCode = 0;
		sStatus.dwCheckPoint = 0;
		sStatus.dwWaitHint = 0;
	}

	if (sStatus.dwCurrentState == SERVICE_START_PENDING)
		sStatus.dwCheckPoint = ++sCheckpoint;
	else
		sStatus.dwCheckPoint = 0;

	sStatus.dwCurrentState = inCurrentState;
	sStatus.dwServiceSpecificExitCode = inExitCode;
	BOOL theErr = SetServiceStatus(sServiceStatusHandle, &sStatus);
	if (theErr == 0)
	{
		DWORD theerrvalue = ::GetLastError();
	}
}

void RunAsService(char* inServiceName)
{
	SC_HANDLE   theService;
	SC_HANDLE   theSCManager;

	theSCManager = ::OpenSCManager(
		NULL,                   // machine (NULL == local)
		NULL,                   // database (NULL == default)
		SC_MANAGER_ALL_ACCESS   // access required
	);
	if (!theSCManager)
		return;

	theService = ::OpenService(
		theSCManager,               // SCManager database
		inServiceName,               // name of service
		SERVICE_ALL_ACCESS);

	SERVICE_STATUS lpServiceStatus;

	if (theService)
	{
		const INT32 kNotRunning = 1062;
		BOOL stopped = ::ControlService(theService, SERVICE_CONTROL_STOP, &lpServiceStatus);
		if (!stopped && ((INT32) ::GetLastError() != kNotRunning))
			//qtss_printf("Stopping Service Error: %d\n", ::GetLastError());
			;//LOGINFO("Stopping Service Error: %d", ::GetLastError());

		BOOL started = ::StartService(theService, 0, NULL);
		if (!started)
			//qtss_printf("Starting Service Error: %d\n", ::GetLastError());
			;//LOGINFO("Starting Service Error: %d", ::GetLastError());

		::CloseServiceHandle(theService);
	}

	::CloseServiceHandle(theSCManager);
}

void StopService(char* inServiceName)
{
	SC_HANDLE   theService;
	SC_HANDLE   theSCManager;

	theSCManager = ::OpenSCManager(
		NULL,                   // machine (NULL == local)
		NULL,                   // database (NULL == default)
		SC_MANAGER_ALL_ACCESS   // access required
	);
	if (!theSCManager)
		return;

	theService = ::OpenService(
		theSCManager,               // SCManager database
		inServiceName,               // name of service
		SERVICE_ALL_ACCESS);

	SERVICE_STATUS lpServiceStatus;

	if (theService)
	{
		const INT32 kNotRunning = 1062;
		BOOL stopped = ::ControlService(theService, SERVICE_CONTROL_STOP, &lpServiceStatus);
		if (!stopped && ((INT32) ::GetLastError() != kNotRunning))
			//qtss_printf("Stopping Service Error: %d\n", ::GetLastError());
			;//LOGINFO("Stopping Service Error: %d", ::GetLastError());

		::CloseServiceHandle(theService);
	}

	::CloseServiceHandle(theSCManager);
}